/**
 * @file boards\gd32f103cb\bsp\bsp_ioi2c.c
 *
 * Copyright (C) 2023
 *
 * bsp_ioi2c.c is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author HinsShum hinsshum@qq.com
 *
 * @encoding utf-8
 */

/*---------- includes ----------*/
#include "gd32f30x_libopt.h"
#include "i2c_bus.h"
#include "options.h"


/*---------- macro ----------*/
/*---------- type define ----------*/
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
#define HTR3236_SDA_PORT (GPIOB)
#define HTR3236_SDA_PIN (GPIO_PIN_7)
#define HTR3236_SCL_PORT (GPIOB)
#define HTR3236_SCL_PIN (GPIO_PIN_6)

static bool bsp_init(void);
static void bsp_deinit(void);
static void bsp_scl_set(bool on);
static bool bsp_scl_get(void);
static void bsp_sda_set(bool on);
static bool bsp_sda_get(void);
static void bsp_delay(void);

/*---------- variable ----------*/
static i2c_bus_describe_t htr_iic = { .data = NULL,
                                     .ops.init = bsp_init,
                                     .ops.deinit = bsp_deinit,
                                     .ops.scl_set = bsp_scl_set,
                                     .ops.scl_get = bsp_scl_get,
                                     .ops.sda_set = bsp_sda_set,
                                     .ops.sda_get = bsp_sda_get,
                                     .ops.delay = bsp_delay,
                                     .ops.lock = NULL,
                                     .ops.unlock = NULL };
DEVICE_DEFINED(htr_iic, i2c_bus, &htr_iic);

/*---------- function ----------*/
static bool bsp_init(void) {
  /* I2C GPIO:
   *  SCL: GPIOB6
   *  SDA: GPIOB7
   */
    rcu_periph_clock_enable(RCU_GPIOB);
    gpio_init(HTR3236_SDA_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ,
        HTR3236_SDA_PIN);
    gpio_init(HTR3236_SCL_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ,
        HTR3236_SCL_PIN);
    gpio_bit_set(HTR3236_SDA_PORT, HTR3236_SDA_PIN);
    gpio_bit_set(HTR3236_SCL_PORT, HTR3236_SCL_PIN);
    return true;
}

static void bsp_deinit(void) {
    gpio_init(HTR3236_SDA_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ,
        HTR3236_SDA_PIN);
    gpio_init(HTR3236_SCL_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ,
        HTR3236_SCL_PIN);
    gpio_bit_set(HTR3236_SDA_PORT, HTR3236_SDA_PIN);
    gpio_bit_set(HTR3236_SCL_PORT, HTR3236_SCL_PIN);
}

static void bsp_scl_set(bool on) {
    if (on) {
        gpio_bit_set(HTR3236_SCL_PORT, HTR3236_SCL_PIN);
    }
    else {
        gpio_bit_reset(HTR3236_SCL_PORT, HTR3236_SCL_PIN);
    }
}

static bool bsp_scl_get(void) {
    return (SET == gpio_input_bit_get(HTR3236_SCL_PORT, HTR3236_SCL_PIN));
}

static void bsp_sda_set(bool on) {
    if (on) {
        gpio_bit_set(HTR3236_SDA_PORT, HTR3236_SDA_PIN);
    }
    else {
        gpio_bit_reset(HTR3236_SDA_PORT, HTR3236_SDA_PIN);
    }
}

static bool bsp_sda_get(void) {
    return (SET == gpio_input_bit_get(HTR3236_SDA_PORT, HTR3236_SDA_PIN));
}

static void bsp_delay(void) { __delay_us(5); }
